package cn.ibizlab.odoo.util.helper;

import cn.ibizlab.odoo.util.filter.SearchContext;
import cn.ibizlab.odoo.util.filter.SearchFieldFilter;
import cn.ibizlab.odoo.util.filter.SearchFilter;
import cn.ibizlab.odoo.util.filter.SearchGroupFilter;
import cn.ibizlab.odoo.util.enums.SearchFieldType;
import cn.ibizlab.odoo.util.enums.SearchGroupType;
import com.google.common.base.CaseFormat;
import org.springframework.data.domain.Sort;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Odoo接口查询条件转换工具类
 */
public class OdooSearchContextHelper {

    public static String getSorts(SearchContext context){
        if(context.getPageable().getSort()==null)
            return "";
        Sort sort = context.getPageable().getSort();
        return sort.stream().map(order -> CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order.getProperty().replace("_text","")) + " " + order.getDirection()).collect(Collectors.joining(","));
    }

    public static List getConditions(SearchContext context){
        List<SearchFilter> searchFilters = context.getCondition();
        List<Object> conditions = new ArrayList<Object>();
        if(searchFilters.size()==0)
            return Arrays.asList(conditions);
        String defaultGroupType="&"; //odoo默认一级组内关系：AND
        for(SearchFilter filter: searchFilters){//条件查询
            List<Object> cond = null;
            if(filter instanceof SearchFieldFilter){ //单条件查询
                cond = parseFieldCond((SearchFieldFilter) filter);
            }
            else if (filter instanceof SearchGroupFilter){//组条件查询
                cond = parseGroupCond((SearchGroupFilter) filter);
            }

            if(cond.size()>0)
                conditions.add(cond);
        }
        return Arrays.asList(conditions);
    }

    /**
     * 字段条件解析
     * @param field
     * @return
     */
    private static List<Object> parseFieldCond(SearchFieldFilter field){
        List<Object> cond = null;
        String param=field.getParam();
        SearchFieldType condtype=field.getCondition();
        Object value=field.getValue();
        if(StringUtils.isEmpty(param)|| StringUtils.isEmpty(condtype))
            return cond;

        switch (condtype){
            case GT:
                cond =  Arrays.asList(param ,">",value); break;
            case GTANDEQ:
                cond =  Arrays.asList(param,">=" ,value); break;
            case EQ:
                cond =  Arrays.asList(param ,"=",value); break;
            case NOTEQ:
                cond =  Arrays.asList(param,"!=",value); break;
            case LT:
                cond =  Arrays.asList(param ,"<",value); break;
            case LTANDEQ:
                cond =  Arrays.asList(param ,"<=",value); break;
            case LIKE:
                cond =  Arrays.asList(param ,"like",value); break;
            case LEFTLIKE:
                cond =  Arrays.asList(param ,"=like","%"+ value); break;
            case RIGHTLIKE:
                cond =   Arrays.asList(param ,"=like",value+"%"); break;
            case ISNULL:
                //暂不支持
            case ISNOTNULL:
                //暂不支持
            case IN:
                if(value instanceof List){
                    List list = (List<String>) value;
                    if(list.size()>0)
                        cond =  Arrays.asList(param ,"in",value); break;
                }
                break;
            case NOTIN:
                if(value instanceof List){
                    List list = (List<String>) value;
                    if(list.size()>0)
                        cond =  Arrays.asList(param ,"not in",value); break;
                }
                break;
        }
        return cond;
    }

    /**
     * 组条件解析
     * @param group
     * @return
     */
    private static List<Object> parseGroupCond(SearchGroupFilter group){
        List<Object> conditions = new ArrayList<Object>();
        List<SearchFilter> groupCond=group.getCondition();//组内条件
        SearchGroupType groupType=group.getSearchGroupType();//组内条件的组合关系(AND/OR)
        if(groupCond.size()==0 || StringUtils.isEmpty(groupType))
            return conditions;
        String strGroupType=getGroupType(groupType);

        //Odoo条件组仅支持附加两个条件，若要进行两个以上条件复合需要在前方附加组符号
        for(int i = 0;i<groupCond.size()-1;i++)
        {
            conditions.add(strGroupType);
        }
        for(SearchFilter filter: groupCond){//条件查询
            List<Object> cond = null;
            if(filter instanceof SearchFieldFilter){ //单条件查询
                cond = parseFieldCond((SearchFieldFilter) filter);
                if(cond.size()>0)
                    conditions.addAll(cond);
            }
            else if (filter instanceof SearchGroupFilter){//组条件查询
                cond = parseGroupCond((SearchGroupFilter) filter);
                if(cond.size()>0)
                    conditions.addAll(cond);
            }
        }

        return conditions;
    }

    /**
     * 组内条件的组合关系(AND/OR)
     * @param groupType
     * @return
     */
    private static String getGroupType(SearchGroupType groupType){
        String strGroupType="";
        switch(groupType){
            case AND: strGroupType="&";break;
            case OR: strGroupType="|"; break;
        }
        return strGroupType;
    }

}
